var customerJS = {
    "handlebars": "../../assets/lib/layui/lay/modules/hdb/handlebars-v4.0.5.js", // 模板引擎
    "showGrid": "../../assets/lib/layui/customer/showGrid.js", // 非表格分页加载插件
    "city": "../../json/city.js", // 地址
    "fontawesomeAll": "../../assets/lib/fontawesome-free-5.11.2/css/all.css", // fontawesome5
    "fontawesomev4": "../../assets/lib/fontawesome-free-5.11.2/css/v4-shims.css", // fontawesome4兼容版
    "systemCommonUtil": "../../assets/lib/layui/customer/common/systemCommonUtil.js", // 系统工具函数
    "systemDateUtil": "../../assets/lib/layui/customer/systemDateUtil.js", // 日期工具函数
    "calculationUtil": "../../assets/lib/layui/customer/calculationUtil.js", // 加减乘除工具函数
    "ajaxPostUtil": "../../assets/lib/layui/customer/ajaxPostUtil.js", // ajax工具函数
    "dsFormUtil": "../../assets/lib/layui/customer/skyeye/dsFormUtil.js", // 动态表单工具函数
    "systemModelUtil": "../../assets/lib/layui/customer/systemModelUtil.js", // 系统编辑器模板工具函数
    "ueEditorUtil": "../../assets/lib/layui/customer/ueEditorUtil.js", // ueEditor编辑器工具函数
    "sysCustomerUtil": "../../assets/lib/layui/customer/sysCustomerUtil.js", // 公共工具函数
    "publicKeyCode": "../../assets/lib/layui/customer/publicKeyCode.js", // 快捷键
    "indexMenu": "../../assets/lib/layui/customer/indexMenu.js", // 菜单按钮模块相关工具
    "codeDocUtil": "../../assets/lib/layui/customer/codeDocUtil.js", // 代码生成器相关工具类
    "threeUtil": "../../assets/lib/layui/customer/threeUtil.js", // 3D编辑器相关工具类
    "initTableChooseUtil": "../../assets/lib/layui/customer/tableUtil/initTableChooseUtil.js", // 加载表格选择的表格插件
    "initTableSearchUtil": "../../assets/lib/layui/customer/tableUtil/initTableSearchUtil.js", // 表格高级查询插件
    "teamObjectPermissionUtil": "../../assets/lib/layui/customer/teamObjectPermissionUtil.js", // 团队成员权限插件
    "catalogTreeUtil": "../../assets/lib/layui/customer/tree/catalogTreeUtil.js", // 目录功能的工具类
};

let titleColor = ["layui-bg-blue", "layui-bg-red", "layui-bg-orange", "layui-bg-black", "layui-bg-gray", "layui-bg-green", "layui-bg-cyan"];

// 登录界面赋值
var env = '';

const cachePrefix = "skyeyeLayui_";
const userTokenKey = cachePrefix + "userToken";
// 租户id的key
var tenantIdKey = cachePrefix + "tenantId";
// 系统基础信息json的key
const sysMainMationKey = cachePrefix + "sysMainMation";

//系统基础信息
var sysMainMation = {}; // 系统基础信息json
if (isNull(localStorage.getItem(sysMainMationKey))) {
    jsGetJsonFile("../../configRation.json?env=" + env, function (data) {
        sysMainMation = data;
        localStorage.setItem(sysMainMationKey, JSON.stringify(sysMainMation));
        initBaseParams();
    });
} else {
    sysMainMation = JSON.parse(unescape(localStorage.getItem(sysMainMationKey)));
    initBaseParams();
}

function getOffice() {
    var office = sysMainMation.office;
    if (isNull(office)) {
        return {};
    }
    return parseConfigToJson(office);
}

var getTenantConfig = function () {
    let tenantConfigStr = sysMainMation.tenant
    if (tenantConfigStr != null && tenantConfigStr != '' && tenantConfigStr != 'undefined') {
        tenantConfigStr = tenantConfigStr.replaceAll("{", "").replaceAll("}", "").replaceAll(" ", "");
        return tenantConfigStr.split(',').reduce(function (result, item) {
            var parts = item.split('=');
            result[parts[0]] = parts[1];
            return result;
        }, {});
    }
    return {};
}

/**
 * 获取租户是否启用
 * @returns true 启用，false 未启用
 */
const tenantEnable = function () {
    return getTenantConfig().enable == 'true';
    // return true;
}

const setTenantId = function (tenantId) {
    localStorage.setItem(tenantIdKey, tenantId);
}

const getTenantId = function () {
    return localStorage.getItem(tenantIdKey);
}

var dsFormPageUrl = "../../tpl/dsFormPage/pageShow.html?pageId=";
var reportPageShowUrl = "../../tpl/reportPage/reportPageShow.html?id=";

var skyeyeVersion;
// 文件路径
var fileBasePath;
// 接口请求地址
var reqBasePath; // 总项目
var shopBasePath; // 商城项目
var flowableBasePath; // 工作流相关功能的项目
var schoolBasePath; // 学校模块请求地址
var reportBasePath; // 报表模块请求地址
var homePagePath; // 前端请求地址
var webSocketPath;//聊天socket-开发

function initBaseParams() {
    skyeyeVersion = sysMainMation.skyeyeVersion;
    fileBasePath = sysMainMation.fileBasePath;
    // sysMainMation.reqBasePath = "http://172.18.71.210:8081/";
    // sysMainMation.emailBasePath= "http://172.18.71.41:8103/";
    reqBasePath = sysMainMation.reqBasePath;
    shopBasePath = sysMainMation.shopBasePath;
    webSocketPath = sysMainMation.webSocketPath;
    flowableBasePath = sysMainMation.flowableBasePath;
    homePagePath = sysMainMation.homePagePath;
    schoolBasePath = sysMainMation.schoolBasePath;
    reportBasePath = sysMainMation.reportBasePath;
}

var serviceMap = [
    { "id": "sysMainMation.reqBasePath", "name": "基础服务" },
    { "id": "sysMainMation.shopBasePath", "name": "商城服务" },
    { "id": "sysMainMation.flowableBasePath", "name": "工作流相关功能的服务" },
    { "id": "sysMainMation.schoolBasePath", "name": "学校服务" },
    { "id": "sysMainMation.reportBasePath", "name": "报表服务" },
    { "id": "sysMainMation.surveyBasePath", "name": "问卷服务" },
    { "id": "sysMainMation.noteBasePath", "name": "笔记服务" },
    { "id": "sysMainMation.rmprogramBasePath", "name": "小程序设计服务" },
    { "id": "sysMainMation.knowlgBasePath", "name": "知识库服务" },
    { "id": "sysMainMation.mailBasePath", "name": "通讯录服务" },
    { "id": "sysMainMation.diskCloudBasePath", "name": "云盘服务" },
    { "id": "sysMainMation.emailBasePath", "name": "邮箱服务" },
    { "id": "sysMainMation.scheduleBasePath", "name": "日程服务" },
    { "id": "sysMainMation.businessFlowBasePath", "name": "业务流程规划服务" },
    { "id": "sysMainMation.noticeBasePath", "name": "公告服务" },
    { "id": "sysMainMation.forumBasePath", "name": "论坛服务" },
    { "id": "sysMainMation.jobdiaayBasePath", "name": "日报服务" },
    { "id": "sysMainMation.ehrBasePath", "name": "EHR服务" },
    { "id": "sysMainMation.lightAppBasePath", "name": "轻应用服务" },
    { "id": "sysMainMation.wagesBasePath", "name": "薪资服务" },
    { "id": "sysMainMation.crmBasePath", "name": "CRM服务" },
    { "id": "sysMainMation.ifsBasePath", "name": "IFS财务服务" },
    { "id": "sysMainMation.erpBasePath", "name": "ERP+生产服务" },
    { "id": "sysMainMation.checkworkBasePath", "name": "考勤服务" },
    { "id": "sysMainMation.bossBasePath", "name": "招聘服务" },
    { "id": "sysMainMation.admBasePath", "name": "行政服务" },
    { "id": "sysMainMation.projectBasePath", "name": "PM项目服务" },
    { "id": "sysMainMation.sealServiceBasePath", "name": "售后工单服务" },
    { "id": "sysMainMation.autoBasePath", "name": "自动化服务" },
    { "id": "sysMainMation.wallBasePath", "name": "表白墙服务" },
    { "id": "sysMainMation.tmsBasePath", "name": "物流服务" },
]

function getRequestHeaders() {
    return {
        userToken: getCookie(userTokenKey),
        loginPCIp: returnCitySN["cip"],
        tenantId: getTenantId()
    };
}
function setRequestHeaders(xmlhttp) {
    var headers = getRequestHeaders();
    $.each(headers, function (key, value) {
        xmlhttp.setRequestHeader(key, value);
    });
}

// 编辑加载自定义的js文件
layui.each(customerJS, function (key, jsPath) {
    if (jsPath.lastIndexOf(".js") >= 0) {
        document.write('<script type="text/javascript" src="' + jsPath + '?v=' + skyeyeVersion + '"></script>');
    } else {
        document.write('<link rel="stylesheet" type="text/css" href="' + jsPath + '?v=' + skyeyeVersion + '"/>');
    }
});

// 操作添加或者编辑时，判断表格是否需要刷新,为0则刷新，否则则不刷新
var refreshCode = "";
// 返回父页面的数据
var turnData = "";

/**
 * 打开新的窗口
 * @param url
 * @param params
 * @param title
 */
function _openNewWindows(mation) {
    if (isNull(mation.url)) {
        winui.window.msg("页面路径不能为空", { icon: 2, time: 2000 });
        return;
    }
    if (isNull(mation.pageId)) {
        winui.window.msg("缺少页面ID", { icon: 2, time: 2000 });
        return;
    }
    if (isNull(mation.title)) {
        mation.title = "窗口";
    }
    if (!isNull(mation.params)) {
        var s = "";
        for (var param in mation.params)
            s += "&" + param + "=" + mation.params[param];
        mation.url = mation.url + "?" + s.slice(1);
    }
    mation.url = systemCommonUtil.getHasVersionUrl(mation.url);
    if (isNull(mation.area)) {
        if (mation.maxmin) {
            mation.area = ['100vw', '100vh'];
        } else {
            mation.area = ['90vw', '90vh'];
        }
    }
    if (isNull(mation.offset)) {
        mation.offset = 'auto';
    }
    if (isNull(mation.maxmin)) {//是否最大化
        mation.maxmin = false;
    }
    if (isNull(mation.shade) && mation.shade != false && mation.shade != 0) {//遮罩层
        mation.shade = 0.5;
    }
    if (isNull(mation.closeBtn) && mation.closeBtn != '0') {//关闭按钮
        mation.closeBtn = 1;
    }
    if (isNull(mation.skin)) {//用户自定义皮肤或者层级
        mation.skin = '';
    }
    refreshCode = "";
    turnData = "";
    var pageIndex = layer.open({
        id: mation.pageId,
        type: 2,
        skin: mation.skin,
        title: mation.title,
        content: mation.url,
        area: mation.area,
        offset: mation.offset,
        maxmin: mation.maxmin,
        shade: mation.shade,
        zIndex: mation.zIndex,
        scrollbar: false,
        closeBtn: mation.closeBtn,
        end: function () {
            if (typeof (mation.callBack) == "function") {
                if (refreshCode == '0') {
                    mation.callBack(refreshCode, turnData);
                } else if (refreshCode == '-9999') {
                    winui.window.msg(systemLanguage["com.skyeye.operationFailed"][languageType], { icon: 2, time: 2000 });
                }
            }
        },
        success: function () {
            var times = layui.$("#" + mation.pageId).parent().attr("times");
            var zIndex = layui.$("#" + mation.pageId).parent().css("z-index");
            layui.$("#layui-layer-shade" + times).css({ 'z-index': zIndex });
            if (typeof (mation.success) == "function") {
                mation.success();
            }
        }
    });
    if (mation.maxmin) {
        layer.full(pageIndex);
    }
}

/**
 * 根据页面高度进行分页
 * @return {}
 */
function getLimits() {
    var limit = getLimit();
    var limits = new Array();
    for (var i = 1; i <= 7; i++) {
        limits.push(limit * i);
    }
    return limits;
}

function getLimit() {
    var clientHeight = document.body.clientHeight;
    var toolbarHeight = $(".winui-toolbar").outerHeight(true);
    var txtcenterHeight = $(".txtcenter").outerHeight(true);
    var winuiTip = $(".winui-tip").outerHeight(true);
    var tabTtileHeight = $(".layui-tab-title").outerHeight(true);
    // 计算表格tbody的高度
    var realHeight = clientHeight - 120
        - (isNull(toolbarHeight) ? 0 : toolbarHeight)
        - (isNull(txtcenterHeight) ? 0 : txtcenterHeight)
        - (isNull(winuiTip) ? 0 : winuiTip)
        - (isNull(tabTtileHeight) ? 0 : tabTtileHeight);
    // 计算limit
    var limit = decimerFiveOrZero(Math.floor(realHeight / 48));
    return limit == 0 ? 5 : limit;
}

function decimerFiveOrZero(number) {
    var newNum = Math.floor(number / 5);
    return newNum * 5 < 0 ? 10 : newNum * 5;
}


/**
 * 根据数据展示
 */
function showDataUseHandlebars(id, source, data) {
    //预编译模板
    var template = Handlebars.compile(source);
    //匹配json内容
    var html = template(data);
    //输入模板
    layui.$("#" + id).html(html);
}

function getDataUseHandlebars(source, data) {
    //预编译模板
    var template = Handlebars.compile(source);
    //匹配json内容
    var html = template(data);
    //输入模板
    return html;
}

var postDownLoadFile = function (options) {
    var config = layui.$.extend(true, {
        method: 'post'
    }, options);
    var $iframe = layui.$('<iframe id="down-file-iframe" />');
    var $form = layui.$('<form target="down-file-iframe" method="' + config.method + '" />');
    $form.attr('action', config.url);
    if (!isNull(config.params)) {
        for (var key in config.params) {
            $form.append('<input type="hidden" name="' + key + '" value="' + config.params[key] + '" />');
        }
    }
    $form.append('<input type="hidden" name="userToken" value="' + getCookie(userTokenKey) + '" />');
    // 图片
    if (!isNull(config.data)) {
        $form.append('<input type="hidden" name="base64Info" value="' + config.data + '" />');
    }

    $iframe.append($form);
    layui.$(document.body).append($iframe);
    $form[0].submit();
    $iframe.remove();
}

/**
 * 权限验证
 * @param urlNum
 */
function auth(urlNum) {
    var authList = JSON.parse(localStorage.getItem("authpoints"));
    if (!isNull(authList)) {
        for (var i = 0; i < authList.length; i++) {
            if (authList[i].menuNum === urlNum) {
                return true;
            } else {
                // 数据权限分组不为空
                if (!isNull(authList[i].children) && authList[i].children.length > 0) {
                    var dataGroup = authList[i].children;
                    for (var j = 0; j < dataGroup.length; j++) {
                        // 数据权限不为空
                        if (!isNull(dataGroup[j].children) && dataGroup[j].children.length > 0) {
                            var dataAuthPoint = dataGroup[j].children;
                            for (var k = 0; k < dataAuthPoint.length; k++) {
                                if (dataAuthPoint[k].menuNum === urlNum) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
    } else {
        winui.window.msg('登录超时，即将返回登录页面.', { icon: 2, time: 2000 }, function () {
            var win = window;
            while (win != win.top) {
                win = win.top;
            }
            win.location.href = "../../tpl/index/login.html";
        });
    }
    return false;
}

function authBtn(urlNum) {
    if (!auth(urlNum)) {
        layui.$('[auth="' + urlNum + '"]').remove();
    }
}

/**
 * 加载列表接口的数据权限菜单，因为要和表格搜索结合到一起，所以监听事件是要去 initTableSearchUtil.js中查看
 *
 * @param tableId 表格id
 * @param urlNum 权限点id
 */
function loadAuthBtnGroup(tableId, urlNum) {
    if (isNull(urlNum)) {
        return;
    }
    var authList = JSON.parse(localStorage.getItem("authpoints"));
    if (!isNull(authList)) {
        var str = '';
        for (var i = 0; i < authList.length; i++) {
            if (authList[i].menuNum === urlNum && !isNull(authList[i].children) && authList[i].children.length > 0) {
                // 数据权限分组不为空
                var dataGroup = authList[i].children;
                for (var j = 0; j < dataGroup.length; j++) {
                    str += `<div style="" class="type-group" id="${dataGroup[j].authMenu}">`;
                    // 数据权限不为空
                    if (dataGroup[j].children.length > 0) {
                        var dataAuthPoint = dataGroup[j].children;
                        dataAuthPoint.sort(function (a, b) {
                            if (isNull(a.orderBy)) {
                                a.orderBy = 0;
                            }
                            if (isNull(b.orderBy)) {
                                b.orderBy = 0;
                            }
                            return a.orderBy - b.orderBy; // 升序排序
                        });
                        for (var k = 0; k < dataAuthPoint.length; k++) {
                            var type = dataAuthPoint[k].authMenu.split('==')[1].trim();
                            var defaultClassName = k == 0 ? 'plan-select' : '';
                            str += `<button type="button" class="layui-btn layui-btn-primary type-btn ${defaultClassName}" data-type="${type}" table-id="${tableId}"><i class="layui-icon"></i>${dataAuthPoint[k].name}</button>`;
                        }
                    }
                    str += `</div>`;
                }
            }
        }
        $(".winui-toolbar").before(str);
    }
}

/***********************************ztree节点查找开始***************************************/

/**
 * 查找子结点，如果找到，返回true，否则返回false-----ztree查询时使用
 */
function searchChildren(keyword, children) {
    if (children == null || children.length == 0) {
        return false;
    }
    for (var i = 0; i < children.length; i++) {
        var node = children[i];
        if (node.name.indexOf(keyword) != -1) {
            return true;
        }
        //递归查找子结点
        var result = searchChildren(keyword, node.children);
        if (result) {
            return true;
        }
    }
    return false;
}

/**
 * 查找当前结点和父结点，如果找到，返回ture，否则返回false
 */
function searchParent(keyword, node) {
    if (node == null) {
        return false;
    }
    if (node.name.indexOf(keyword) != -1) {
        return true;
    }
    //递归查找父结点
    return searchParent(keyword, node.getParentNode());
}
/***********************************ztree节点查找结束***************************************/

/**
 * echarts简单图形参数
 * @param {} title		标题
 * @param {} subtext	描述
 * @param {} xNameData	x轴数据，数组类型
 * @param {} yTitle		y轴标题
 * @param {} yNameData	y轴数据，数组类型
 * @param {} type		图形展示类型。line：折线图；bar：柱形图
 * @return {}
 */
function getOption(title, subtext, xNameData, yTitle, yNameData, type) {
    return {
        color: ['#3398DB', '#FFB6C1', '#C71585', '#8B008B', '#4169E1', '#00BFFF', '#008B8B'],
        title: {
            text: title,
            x: 'center',
            subtext: subtext
        },
        tooltip: {
            trigger: 'axis',
            axisPointer: {            			// 坐标轴指示器，坐标轴触发有效
                type: 'shadow'        			// 默认为直线，可选为：'line' | 'shadow'
            }
        },
        toolbox: {
            show: true,							//是否显示工具栏组件
            orient: "horizontal",				//工具栏 icon 的布局朝向'horizontal' 'vertical'
            itemSize: 15,						//工具栏 icon 的大小
            itemGap: 10,						//工具栏 icon 每项之间的间隔
            showTitle: true,					//是否在鼠标 hover 的时候显示每个工具 icon 的标题
            feature: {
                mark: {							//'辅助线开关'
                    show: true
                },
                dataView: {					//数据视图工具，可以展现当前图表所用的数据，编辑后可以动态更新
                    show: true,					//是否显示该工具。
                    title: "数据视图",
                    readOnly: false,			//是否不可编辑（只读）
                    lang: ['数据视图', '关闭', '刷新'],	//数据视图上有三个话术，默认是['数据视图', '关闭', '刷新']
                    backgroundColor: "#fff",	//数据视图浮层背景色。
                    textareaColor: "#fff",		//数据视图浮层文本输入区背景色
                    textareaBorderColor: "#333",//数据视图浮层文本输入区边框颜色
                    textColor: "#000",			//文本颜色。
                    buttonColor: "#c23531",		//按钮颜色。
                    buttonTextColor: "#fff"		//按钮文本颜色。
                },
                magicType: {					//动态类型切换
                    show: true,
                    title: "切换",				//各个类型的标题文本，可以分别配置。
                    type: ['line', 'bar']		//启用的动态类型，包括'line'（切换为折线图）, 'bar'（切换为柱状图）, 'stack'（切换为堆叠模式）, 'tiled'（切换为平铺模式）
                },
                restore: {						//配置项还原。
                    show: true,					//是否显示该工具。
                    title: "还原"
                },
                saveAsImage: {					//保存为图片。
                    show: true,					//是否显示该工具。
                    type: "png",				//保存的图片格式。支持 'png' 和 'jpeg'。
                    name: "pic1",				//保存的文件名称，默认使用 title.text 作为名称
                    backgroundColor: "#ffffff",	//保存的图片背景色，默认使用 backgroundColor，如果backgroundColor不存在的话会取白色
                    title: "保存为图片",
                    pixelRatio: 1				//保存图片的分辨率比例，默认跟容器相同大小，如果需要保存更高分辨率的，可以设置为大于 1 的值，例如 2
                },
                dataZoom: {						//数据区域缩放。目前只支持直角坐标系的缩放
                    show: true,					//是否显示该工具。
                    title: "缩放",				//缩放和还原的标题文本
                    xAxisIndex: 0,				//指定哪些 xAxis 被控制。如果缺省则控制所有的x轴。如果设置为 false 则不控制任何x轴。如果设置成 3 则控制 axisIndex 为 3 的x轴。如果设置为 [0, 3] 则控制 axisIndex 为 0 和 3 的x轴
                    yAxisIndex: false			//指定哪些 yAxis 被控制。如果缺省则控制所有的y轴。如果设置为 false 则不控制任何y轴。如果设置成 3 则控制 axisIndex 为 3 的y轴。如果设置为 [0, 3] 则控制 axisIndex 为 0 和 3 的y轴
                }
            }
        },
        xAxis: {
            type: 'category',
            axisLabel: {
                interval: 0,
                formatter: function (value) {
                    var ret = ""; //拼接加\n返回的类目项  
                    var maxLength = 4; //每项显示文字个数  
                    var valLength = value.length; //X轴类目项的文字个数  
                    var rowN = Math.ceil(valLength / maxLength); //类目项需要换行的行数  
                    if (rowN > 1) { //如果类目项的文字大于3,  
                        for (var i = 0; i < rowN; i++) {
                            var temp = ""; //每次截取的字符串  
                            var start = i * maxLength; //开始截取的位置  
                            var end = start + maxLength; //结束截取的位置  
                            //这里也可以加一个是否是最后一行的判断，但是不加也没有影响，那就不加吧  
                            temp = value.substring(start, end) + "\n";
                            ret += temp; //凭借最终的字符串  
                        }
                        return ret;
                    } else {
                        return value;
                    }
                }
            },
            data: xNameData
        },
        yAxis: {
            type: 'value'
        },
        series: [{
            name: yTitle,
            type: isNull(type) ? 'line' : type,
            smooth: true,
            data: yNameData
        }]
    };
}

/**
 * echarts简单图形参数
 * @param {} title		标题
 * @param {} subtext	描述
 * @param {} data	数据
 * @return {}
 */
function getPieChatOption(title, subtext, data) {
    return {
        title: {
            text: title,
            subtext: subtext,
            left: 'center'
        },
        tooltip: {
            trigger: 'item'
        },
        legend: {
            data: [],
            bottom: '5%',
            left: 'center'
        },
        series: [
            {
                name: '',
                type: 'pie',
                radius: '50%',
                data: data,
                emphasis: {
                    itemStyle: {
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                }
            }
        ]
    };
}

// 移除指定value值
function removeByValue(arr, val) {
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] == val) {
            arr.splice(i, 1);
            break;
        }
    }
}

// 取出json串的键
function getOutKey(arr) {
    var jsonObj = $.parseJSON(arr);
    var a = [];
    var b = [];
    for (var i = 0; i < jsonObj.length; i++) {
        for (var key in jsonObj[i])
            a.push(key);
        b.push(a);
        a = [];
    }
    return b;
}

// B的子集是否是A的子集
function subset(A, B) {
    for (var i = 0; i < B.length; i++) {
        if (!isContained(B[i], A)) {
            return false;
        }
    }
    return true;
}

// b是否被a包含,是返回true,不是返回false
isContained = (a, b) => {
    if (!(a instanceof Array) || !(b instanceof Array))
        return false;
    if (a.length < b.length)
        return false;
    var aStr = a.toString();
    for (var i = 0, len = b.length; i < len; i++) {
        if (aStr.indexOf(b[i]) == -1)
            return false;
    }
    return true;
}

/*****************工作计划模块开始**************/
// 获取计划周期名称
function getNowCheckTypeName(nowCheckType) {
    if (nowCheckType === 'day')
        return '日计划';
    else if (nowCheckType === 'week')
        return '周计划';
    else if (nowCheckType === 'month')
        return '月计划';
    else if (nowCheckType === 'quarter')
        return '季度计划';
    else if (nowCheckType === 'halfyear')
        return '半年计划';
    else if (nowCheckType === 'year')
        return '年计划';
}
/*****************工作计划模块结束**************/

function matchingLanguage() {
    var list = layui.$("language");
    if (list.length > 0) {
        $.each(list, function (i, item) {
            if (isNull($(item).html())) {
                $(item).html(systemLanguage[$(item).attr("showName")][languageType]);
            }
        });
    }
    list = layui.$("[matchLanguage]");
    if (list.length > 0) {
        $.each(list, function (i, item) {
            try {
                var jsonStr = $(item).attr("matchLanguage");
                if (!isNull(jsonStr)) {
                    jsonStr = jsonStr.replace(/\'/g, "\"");
                    var _json = JSON.parse(jsonStr);
                    $.each(_json, function (key, value) {
                        if (key === "html") {
                            $(item).html(systemLanguage[value][languageType]);
                        } else {
                            $(item).attr(key, systemLanguage[value][languageType]);
                        }
                    });
                    $(item).removeAttr("matchLanguage");
                }
            } catch (e) {
                console.error(e);
            }
        });
    }
}

function initPasteDragImg(Editor) {
    var doc = document.getElementById(Editor.id)
    doc.addEventListener('paste', function (event) {
        var items = (event.clipboardData || window.clipboardData).items;
        var file = null;
        if (items && items.length) {
            // 搜索剪切板items
            for (var i = 0; i < items.length; i++) {
                if (items[i].type.indexOf('image') !== -1) {
                    file = items[i].getAsFile();
                    break;
                }
            }
        } else {
            winui.window.msg("当前浏览器不支持", { icon: 2, time: 2000 });
            return;
        }
        if (!file) {
            return;
        }
        uploadImg(file, Editor);
    });

    var dashboard = document.getElementById(Editor.id)
    dashboard.addEventListener("dragover", function (e) {
        e.preventDefault()
        e.stopPropagation()
    })
    dashboard.addEventListener("dragenter", function (e) {
        e.preventDefault()
        e.stopPropagation()
    })
    dashboard.addEventListener("drop", function (e) {
        e.preventDefault()
        e.stopPropagation()
        var files = this.files || e.dataTransfer.files;
        uploadImg(files[0], Editor);
    })
}

function uploadImg(file, Editor) {
    var formData = new FormData();
    var fileName = new Date().getTime() + "." + file.name.split(".").pop();
    formData.append('editormd-image-file', file, fileName);
    $.ajax({
        url: Editor.settings.imageUploadURL,
        type: 'post',
        data: formData,
        processData: false,
        contentType: false,
        dataType: 'json',
        success: function (json) {
            if (json.returnCode == 0) {
                var url = json.bean.picUrl;
                var type = url.substr(url.lastIndexOf(".") + 1);
                if ($.inArray(type, imageType) >= 0) {
                    Editor.insertValue("![图片alt](" + url + " ''图片title'')");
                } else {
                    Editor.insertValue("[下载附件](" + url + ")");
                }
            } else {
                winui.window.msg(json.returnMessage, { icon: 2, time: 2000 });
            }
        }
    });
}

/**
 * 判断一个值是否在指定的集合中存在
 *
 * @param array 集合
 * @param key 要比较的key
 * @param value 要比较的值
 * @returns {boolean}
 */
function judgeInPoingArr(array, key, value) {
    if (isNull(array)) {
        return false;
    }
    for (var i = 0; i < array.length; i++) {
        if (array[i][key] == value) {
            return true;
        }
    }
    return false;
}

/**
 * 获取一个值是否在指定的集合中匹配到的值的指定key
 *
 * @param array 集合
 * @param key 要比较的key
 * @param value 要比较的值
 * @param getKey 要获取的值
 * @returns {null|*}
 */
function getInPoingArr(array, key, value, getKey) {
    if (array == null) {
        return null;
    }
    for (var i = 0; i < array.length; i++) {
        if (array[i][key] == value) {
            if (isNull(getKey)) {
                return array[i];
            }
            return array[i][getKey];
        }
    }
    return null;
}

/**
 * 获取集合中一个值是否包含在指定的字符串中，如果包含，则返回
 *
 * @param array 集合
 * @param value 要比较的值
 * @returns {null|*}
 */
function getArrIndexOfPointStr(array, value) {
    for (var i = 0; i < array.length; i++) {
        if (value.indexOf(array[i]) > -1) {
            return array[i];
        }
    }
    return "";
}

/**
 * 获取员工信息
 *
 * @param staffId 员工id
 * @returns {string}
 */
function getUserStaffHtmlMationByStaffId(staffId) {
    var html = "";
    var template = getFileContent('tpl/common/userStaff/userStaffMationShowTop.tpl');
    AjaxPostUtil.request({
        url: reqBasePath + "querySysUserStaffById", params: { id: staffId }, type: 'json', method: "GET", callback: function (json) {
            html = getDataUseHandlebars(template, json);
        }, async: false
    });
    return html;
}

/**
 * 字符串处理
 *
 * @type {{}}
 */
var stringManipulation = {
    textAreaShow: function (str) {
        if (isNull(str)) {
            return '';
        }
        // IE7-8、IE9、FF、chrome。解决textarea中输入的文字，输出到div中文字不换自动换行的问题
        return str.replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>');
    }
};

/**
 * 工作流审批状态显示颜色变更
 *
 * @param state 状态
 * @param stateName 状态中文显示
 * @returns {string}
 */
function getStateNameByState(state, stateName) {
    if (state == '0') {
        stateName = "<span>" + stateName + "</span>";
    } else if (state == '1') {
        stateName = "<span class='state-new'>" + stateName + "</span>";
    } else if (state == '2') {
        stateName = "<span class='state-up'>" + stateName + "</span>";
    } else if (state == '3') {
        stateName = "<span class='state-down'>" + stateName + "</span>";
    } else if (state == '4') {
        stateName = "<span class='state-down'>" + stateName + "</span>";
    } else if (state == '5') {
        stateName = "<span class='state-error'>" + stateName + "</span>";
    }
    return stateName;
}

function returnModel(lang) {
    var type = {
        'Java': 'text/x-java',
        'C/C++': 'text/x-c++src',
        'Objective-C': '',
        'Scala': 'text/x-scala',
        'Kotlin': 'text/x-kotlin',
        'Ceylon': 'text/x-ceylon',
        'xml': 'xml',
        'html': 'xml',
        'jsp': 'xml',
        'css': 'text/css',
        'htmlmixed': 'htmlmixed',
        'htmlhh': 'htmlmixed',
        'javascript': 'text/javascript',
        'nginx': 'text/x-nginx-conf',
        'solr': 'text/x-solr',
        'sql': 'text/x-sql',
        'vue': 'text/x-vue'
    };
    return type[lang];
}

function show(_object, url) {
    if (imageType.indexOf(url.substring(url.lastIndexOf(".") + 1).toLowerCase()) < 0) {
        window.open(url);
        return false;
    }

    var imgs = [];
    if (layui.$.isPlainObject(_object)) {
        imgs = _object.find("input[type='hidden'][name='upload']").val().split(",");
    } else {
        imgs = layui.$(_object).find("input[type='hidden'][name='upload']").val().split(",");
    }
    showPicDisk(imgs, url);
}

/**
 * 展示图片,支持多张图片切换展示
 * @param {} imgs
 * @param {} defaultUrl 默认展示的图片地址
 */
function showPicDisk(imgs, defaultUrl) {
    var data = [];
    let startIndex = 0;
    imgs = imgs.filter(img => !isNull(img));
    layui.$.each(imgs, function (index, img) {
        var suffix = img.substring(img.lastIndexOf(".") + 1);
        if (imageType.indexOf(suffix.toLowerCase()) > -1) {
            var json = {
                "alt": "",
                "pid": index, //图片id
                "src": img, //原图地址
                "thumb": "" //缩略图地址
            }
            data.push(json);
            if (!isNull(defaultUrl) && img.indexOf(defaultUrl) > -1) {
                startIndex = index;
            }
        }
    })

    layer.photos({
        photos: {
            "title": "", //相册标题
            "id": 123, //相册id
            "start": startIndex, //初始显示的图片序号
            "data": data
        }, //格式见API文档手册页
        anim: 5 //0-6的选择，指定弹出图片动画类型，默认随机
    });
}

/**
 * 获取随机值
 * @return {}
 */
function getRandomValueToString() {
    return Date.parse(new Date()) + "" + getRandom(999);
}

/**
 * 生成指定位数的随机整数
 * @param {} n
 * @return {}
 */
function getRandom(n) {
    return Math.floor(Math.random() * n + 1);
}

/**
 * 获取长度为len的随机字符串
 * @param len
 * @returns {String}
 */
function _getRandomString(len) {
    len = len || 32;
    var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; // 默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1
    var maxPos = $chars.length;
    var pwd = '';
    for (i = 0; i < len; i++) {
        pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return pwd;
}

/**
 * 全屏
 */
function fullScreen() {
    var docElm = document.documentElement;
    //W3C
    if (docElm.requestFullscreen) {
        docElm.requestFullscreen();
    }
    //FireFox
    else if (docElm.mozRequestFullScreen) {
        docElm.mozRequestFullScreen();
    }
    //Chrome等
    else if (docElm.webkitRequestFullScreen) {
        docElm.webkitRequestFullScreen();
    }
    //IE11
    else if (docElm.msRequestFullscreen) {
        document.body.msRequestFullscreen();
    }
}

/**
 * 禁用全屏
 */
function exitFullScreen() {
    if (document.fullscreenElement) {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.webkitCancelFullScreen) {
            document.webkitCancelFullScreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        }
    }
}

/**
 * 判断是否是url
 * @param URL
 * @returns {Boolean}
 */
function checkURL(URL) {
    var reg = /(https?|http|ftp|file):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g;
    URL = URL.match(reg);
    if (isNull(URL) || URL.length == 0) {
        return false;
    } else {
        return true;
    }
}

/**
 * 获取 blob
 * @param  {String} url 目标文件地址
 * @return {cb}
 */
function getBlob(url, cb) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';
    xhr.onload = function () {
        if (xhr.status === 200) {
            cb(xhr.response);
        }
    };
    xhr.send();
}

/**
 * 保存
 * @param  {Blob} blob
 * @param  {String} filename 想要保存的文件名称
 */
function saveAs(blob, filename) {
    if (window.navigator.msSaveOrOpenBlob) {
        navigator.msSaveBlob(blob, filename);
    } else {
        var link = document.createElement('a');
        var body = document.querySelector('body');
        link.href = window.URL.createObjectURL(blob);
        link.download = filename;
        // fix Firefox
        link.style.display = 'none';
        body.appendChild(link);
        link.click();
        body.removeChild(link);
        window.URL.revokeObjectURL(link.href);
    };
}

/**
 * 下载
 * @param  {String} url 目标文件地址
 * @param  {String} filename 想要保存的文件名称
 */
function download(url, filename) {
    getBlob(url, function (blob) {
        saveAs(blob, filename);
    });
};

//下载图片
function downloadImage(path, imgName) {
    var _OBJECT_URL;
    var request = new XMLHttpRequest();
    request.addEventListener('readystatechange', function (e) {
        if (request.readyState == 4) {
            _OBJECT_URL = URL.createObjectURL(request.response);
            var $a = $("<a></a>").attr("href", _OBJECT_URL).attr("download", imgName);
            $a[0].click();
        }
    });
    request.responseType = 'blob';
    request.open('get', path);
    request.send();
}

// 判断是否是json
function isJsonFormat(str) {
    try {
        layui.$.parseJSON(str);
    } catch (e) {
        return false;
    }
    return true;
}

/**
 * 判断str在strs中是否存在，strs的数据格式为'folder-item,select'
 * @param strs
 * @param str
 */
function judgeStrInStrs(strs, str) {
    if (!isNull(strs) && !isNull(str)) {
        var ss = strs.split(',');
        var strIndex = -1;
        layui.$.each(ss, function (i, item) {
            if (str === item) {
                strIndex = i;
                return false;
            }
        });
        return strIndex;
    }
    return 0;
}

/**
 * 对象数组根据某个字段进行排序
 * @param order 'desc':'降序', 'asc':'升序'
 * @param sortBy 排序字段
 */
function getSortFun(order, sortBy) {
    var ordAlpah = (order == 'asc') ? '>' : '<';
    var sortFun = new Function('a', 'b', 'return a.' + sortBy + ordAlpah + 'b.' + sortBy + '?1:-1');
    return sortFun;
}

/**
 * 根据某个字段分组
 *
 * @param items
 * @param field
 * @returns {{}}
 */
function groupByField(items, field) {
    var grouped = {};
    $.each(items, function () {
        let value = this[field];
        if (grouped.hasOwnProperty(value)) {
            grouped[value].push(this);
        } else {
            grouped[value] = [this];
        }
    });
    return grouped;
}

/**
 * 判断字符串是否是json字符串
 * @param str
 */
function isJSON(str) {
    if (typeof str == 'string') {
        try {
            var obj = JSON.parse(str);
            if (typeof obj == 'object' && obj) {
                return true;
            } else {
                return false;
            }
        } catch (e) {
            return false;
        }
    } else {
        return false;
    }
}

/**
 * 取出字符串str中以startCode开始，以endCode结束的所有字符串
 * @param str
 * @param startCode
 * @param endCode
 */
function strMatchAllByTwo(str, startCode, endCode) {
    if (str.length > 0) {
        var arr = [];
        var firstStart = str.indexOf(startCode);
        var firstEnd = str.indexOf(endCode);
        arr.push(str.substr(firstStart + startCode.length, firstEnd - firstStart - endCode.length));
        return arr.concat(strMatchAllByTwo(str.substr(firstEnd + endCode.length), startCode, endCode));
    } else {
        return [];
    }
}

function firstLetterUpper(str) {
    if (str.length > 0) {
        return str.charAt(0).toUpperCase() + str.slice(1);
    } else {
        return "";
    }
}

/**
 * 全局监听所有input元素，显示过长内容的完整信息
 * 当鼠标悬停在input上时，会显示完整内容的提示框
 */
(function () {
    // 创建自定义提示元素
    let tooltipEl = null;

    // 当前悬停的元素
    let currentHoverElement = null;

    // 延迟计时器
    let hideTimer = null;
    let showTimer = null;

    // 文档加载完成后执行
    document.addEventListener('DOMContentLoaded', function () {
        // 创建提示元素
        tooltipEl = document.createElement('div');
        tooltipEl.className = 'input-full-content-tooltip';
        tooltipEl.style.cssText = 'position: fixed; z-index: 19891014; background-color: #3595CC; color: #fff; padding: 8px 12px; border-radius: 4px; font-size: 12px; line-height: 1.5; max-width: 300px; word-wrap: break-word; word-break: break-all; white-space: normal; box-shadow: 0 2px 8px rgba(0,0,0,0.15); display: none; overflow-wrap: break-word; text-overflow: ellipsis; line-break: anywhere; pointer-events: none;';
        document.body.appendChild(tooltipEl);

        // 初始化监听所有input元素
        initInputTooltips();

        // 对动态添加的元素也进行监听
        const observer = new MutationObserver(function () {
            initInputTooltips();
        });

        // 监听DOM变化
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // 处理滚动事件
        let scrollTimer = null;
        window.addEventListener('scroll', function () {
            // 使用防抖动处理滚动事件
            if (scrollTimer) clearTimeout(scrollTimer);

            // 先隐藏提示
            if (tooltipEl) tooltipEl.style.display = 'none';

            scrollTimer = setTimeout(function () {
                if (currentHoverElement) {
                    // 重新显示提示
                    showTooltip(currentHoverElement);
                }
            }, 200);
        }, true);

        // 监听窗口大小变化
        window.addEventListener('resize', function () {
            if (currentHoverElement) {
                showTooltip(currentHoverElement);
            }
        });
    });

    // 更新提示框位置
    function updateTooltipPosition(element) {
        if (!element || !tooltipEl) return;

        // 使用getBoundingClientRect获取元素相对于视口的位置
        const rect = element.getBoundingClientRect();

        // 元素是否在视口内
        if (rect.bottom < 0 || rect.top > window.innerHeight ||
            rect.right < 0 || rect.left > window.innerWidth) {
            hideTooltip();
            return;
        }

        // 计算提示框宽度
        const tooltipWidth = Math.min(300, window.innerWidth - 20);

        // 默认显示在元素上方
        let top = rect.top - 10;
        let marginTop = -tooltipEl.offsetHeight;

        // 如果上方空间不足，则显示在元素下方
        if (top - tooltipEl.offsetHeight < 5) {
            top = rect.bottom + 10;
            marginTop = 0;
        }

        // 水平位置，默认与元素左对齐
        let left = rect.left;

        // 调整以确保提示框不超出窗口
        if (left + tooltipWidth > window.innerWidth - 5) {
            left = window.innerWidth - tooltipWidth - 5;
        }

        // 确保提示框不会重叠到输入框
        tooltipEl.style.position = 'fixed';
        tooltipEl.style.top = top + 'px';
        tooltipEl.style.marginTop = marginTop + 'px';
        tooltipEl.style.left = left + 'px';
        tooltipEl.style.maxWidth = tooltipWidth + 'px';
    }

    // 显示提示框
    function showTooltip(element) {
        if (!element || !tooltipEl) return;

        // 清除之前的定时器
        if (hideTimer) {
            clearTimeout(hideTimer);
            hideTimer = null;
        }

        // 检查元素是否在视口内
        const rect = element.getBoundingClientRect();
        if (rect.bottom < 0 || rect.top > window.innerHeight ||
            rect.right < 0 || rect.left > window.innerWidth) {
            hideTooltip();
            return;
        }

        if (element.scrollWidth > element.clientWidth || (element.value && element.value.length > 20)) {
            // 获取输入框的值
            let content = element.value || element.placeholder || '';
            if (!content.trim()) return; // 内容为空则不显示

            // 处理长数字，每2位数字间插入零宽空格强制换行
            if (/\d{10,}/.test(content)) {
                content = content.replace(/(\d{2})(?=\d)/g, '$1\u200B');
            }

            // 设置内容
            tooltipEl.innerHTML = content;

            // 显示提示框
            tooltipEl.style.display = 'block';

            // 更新位置
            updateTooltipPosition(element);
        }
    }

    // 隐藏提示框
    function hideTooltip() {
        if (tooltipEl) {
            tooltipEl.style.display = 'none';
        }
        currentHoverElement = null;
    }

    // 初始化所有input元素的tooltip功能
    function initInputTooltips() {
        const inputs = document.querySelectorAll('input[type="text"], input[type="search"], input:not([type]), textarea');

        inputs.forEach(function (input) {
            // 避免重复添加事件监听
            if (input.getAttribute('data-tooltip-initialized')) {
                return;
            }

            // 鼠标悬停时显示内容
            input.addEventListener('mouseenter', function (e) {
                // 清除可能的隐藏定时器
                if (hideTimer) {
                    clearTimeout(hideTimer);
                    hideTimer = null;
                }

                currentHoverElement = this;

                // 使用延迟显示，减少闪烁
                if (showTimer) clearTimeout(showTimer);
                showTimer = setTimeout(() => {
                    showTooltip(this);
                }, 200);
            });

            // 鼠标移出时延迟关闭提示
            input.addEventListener('mouseleave', function (e) {
                // 清除显示定时器
                if (showTimer) {
                    clearTimeout(showTimer);
                    showTimer = null;
                }

                // 延迟隐藏提示框，减少闪烁
                if (hideTimer) clearTimeout(hideTimer);
                hideTimer = setTimeout(() => {
                    hideTooltip();
                }, 300);
            });

            // 输入内容变化时更新提示
            input.addEventListener('input', function () {
                if (currentHoverElement === this) {
                    showTooltip(this);
                }
            });

            // 标记为已初始化
            input.setAttribute('data-tooltip-initialized', 'true');
        });
    }
})();

/**
 * 将特定格式的配置字符串转换为JSON对象
 *
 * 例如："{check=onlyOffice, kingsoftConfig={server=https://preview.kdocs.cn/office/k, appId=your-app-id}}"
 * 转换为：{"check":"onlyOffice", "kingsoftConfig":{"server":"https://preview.kdocs.cn/office/k", "appId":"your-app-id"}}
 *
 * @param {string} configStr 配置字符串
 * @returns {object} 解析后的JSON对象
 */
function parseConfigToJson(configStr) {
    // 移除最外层的大括号（如果有）
    if (configStr.startsWith('{') && configStr.endsWith('}')) {
        configStr = configStr.substring(1, configStr.length - 1);
    }

    return parseObject(configStr);
}

/**
 * 解析配置字符串为对象
 * @param {string} str 配置字符串内容
 * @returns {object} 解析后的对象
 */
function parseObject(str) {
    const result = {};
    let index = 0;
    let key = '';
    let value = '';
    let inKey = true;

    while (index < str.length) {
        // 跳过空白字符
        if (str[index] === ' ' || str[index] === '\t' || str[index] === '\n' || str[index] === '\r') {
            index++;
            continue;
        }

        // 如果是在解析键
        if (inKey) {
            // 如果遇到等号，表示键结束
            if (str[index] === '=') {
                inKey = false;
                index++;
                continue;
            }

            // 否则累加键名
            key += str[index];
        }
        // 如果是在解析值
        else {
            // 如果值是一个对象（以大括号开始）
            if (str[index] === '{') {
                // 找到匹配的右花括号
                const startPos = index;
                let braceCount = 1;
                index++;

                while (braceCount > 0 && index < str.length) {
                    if (str[index] === '{') braceCount++;
                    if (str[index] === '}') braceCount--;
                    index++;
                }

                // 递归解析子对象
                const objStr = str.substring(startPos + 1, index - 1);
                result[key.trim()] = parseObject(objStr);

                // 重置键值，准备解析下一个键值对
                key = '';
                value = '';
                inKey = true;

                // 跳过逗号（如果有）
                if (index < str.length && str[index] === ',') {
                    index++;
                }
                continue;
            }

            // 如果遇到逗号，表示当前键值对结束
            if (str[index] === ',') {
                result[key.trim()] = processValue(value.trim());
                key = '';
                value = '';
                inKey = true;
                index++;
                continue;
            }

            // 否则累加值
            value += str[index];
        }

        index++;
    }

    // 处理最后一个键值对
    if (key && !inKey) {
        result[key.trim()] = processValue(value.trim());
    }

    return result;
}

/**
 * 处理值的类型转换
 * @param {string} value 值字符串
 * @returns {any} 转换后的值
 */
function processValue(value) {
    // 判断是否为数字
    if (/^-?\d+(\.\d+)?$/.test(value)) {
        return Number(value);
    }

    // 判断是否为布尔值
    if (value === 'true') return true;
    if (value === 'false') return false;

    // 判断是否为null
    if (value === 'null') return null;

    // 默认为字符串
    return value;
}
